// const CHOSEN_RECORDS = []; //监听被选中的描述词

window.onload = function () {

    dataStore = new Hooker();

    candidPool = new CandidPool();
    chosenArray = new ChosenArray(candidPool);
    dimPool = new DimPool();
    emptyBtn = new EmptyAll();

    dimPool._getData();
    emptyBtn._bindEvents();
}


// 虾米对象：所有等待挂钩对象的父类
class Shrimp {
    constructor(param = new Object, bait = new String) {
        bait = bait + '';
        if(bait.length > 0 && (Object.keys(param).indexOf(bait) < 0 || !param[bait])) {
            throw TypeError("No any BAIT found in arguments!");
        }

        // 设置数据双向绑定的鱼饵，若设置鱼饵，则鱼饵的值不能为空
        this._bait = bait || null;

        // 设置钩子
        if(!dataStore) {
            throw TypeError("No any HOOKER found!");
        }
        this.hooker = dataStore;

        for(let [key, value] of Object.entries(param)) {
            if(!key || !value) {continue;}
            this[key] = value;
        }

        this._bindEvents();
    }

    getBait () {
        return this._bait;
    }

    setter () {
        console.log("SETTER");
    }

    getter () {
        console.log("GETTER");
        return 3;
    }

    _bindEvents () {
        this.hooker.logIn(this);
    }
}

class S1 extends Shrimp {
    constructor(param, bait) {
        super(param, bait);
        console.log(this.param);
    }
}


class DimPool {
    constructor() {
        this.panel = document.querySelector("#multi_choice");
        this.pool = document.createElement("div");

        this.target_box = document.querySelector("#desc_pool"); // 受相应的描述词区域容器
        this.data = null;
        this.item_list = new Array;
    }

    _getData () {
        let that = this;
        $.ajax({
            // url: "https://jkalan6991.gitee.io/video-explorer/assets/static/homepage_ex.html",
            url: "http://124.220.168.234/api/dims/",
            type: "GET",
            contentType: "application/json",
            dataType: "json",
            success: function(res) {
                that._loadDims(res["results"]);
            }
        });
    }

    _loadDims (json) {
        if(json.length <= 0) {
            return null;
        }

        this.item_list = [];

        json.forEach((dim_doc, i, _) => {
            let {dim_id, dim_name} = dim_doc;
            let dim_item = new DimItem(dim_id, dim_name);

            dim_item._bindEvents(this.target_box);
            // insert item object to the pool & list
            this.item_list.push(dim_item);
            this.pool.appendChild(dim_item.dim_item);
        });

        this.panel.appendChild(this.pool);
    }
}

class DimItem {
    constructor(dim_id, dim_name) {
        this.dim_id = dim_id;
        this.dim_name = dim_name;

        this.v_name = dim_name
        if(dim_name.indexOf('.') >= 0) {
            this.v_name = this.v_name.split('.')[1];
        }
        
        this.v_name = dim_id + '.' + this.v_name.split('-').slice(-2,).join('-');

        // create item node
        this.dim_item = this._createItem();
    }

    // create item node
    _createItem () {
        let dim_item = document.createElement("div");
        let dim_icon = document.createElement("span");
        let dim_name = document.createElement("span");

        dim_item.classList.add("dim_item", "btn");
        dim_icon.innerHTML = `<div class="dim_icon">${""}</div>`;
        dim_name.innerHTML = `<div class="dim_name">${this.v_name}</div>`;

        // insert to card-inner
        [dim_icon, dim_name].forEach(
            (node, i, nodeList) => dim_item.appendChild(node)
        );

        return dim_item;
    }

    _bindEvents (target_box) {
        this.dim_item.addEventListener("click", () => {
            desc_list = loadDescs(this.dim_id);
            target_box.innerHTML = "";
            desc_list.forEach(
                (desc_item, _id, _) => {
                    // if(CHOSEB_RECORDS.indexOf(desc_item.name_code) >= 0) {
                    //     desc_item.desc_item.classList.add("active");
                    // }
                    target_box.appendChild(desc_item.desc_item);
                }
            );
        });

        this.dim_item.addEventListener("click", () => {
            if(!this.dim_item.classList.contains("active")) {
                document.querySelectorAll(".dim_item.active").forEach((node, _id, _) => {
                    node.classList.remove("active");
                });
            }
            this.dim_item.classList.add("active");
        })
    }
}

class DescItem {
    constructor(desc_id, dim_id, desc_name) {
        this.desc_id = desc_id;
        this.dim_id =dim_id
        this.desc_name = desc_name;
        this.name_code = this.dim_id+"_"+this.desc_name;

        // create item node
        this.desc_item = this._createItem();
        this.desc_item.setAttribute("n_code", this.name_code);

        // 判断是否已被选中
        if (chosenArray.CHOSEN_RECORDS.indexOf(this.name_code) >= 0) {
            this.desc_item.classList.add("active");
        }
    }

    // create item node
    _createItem () {
        let desc_item = document.createElement("div");
        let desc_icon = document.createElement("span");
        let desc_name = document.createElement("span");

        desc_item.classList.add("desc_item", "btn");
        desc_icon.classList.add("desc_icon");
        desc_name.classList.add("desc_name");
        desc_name.innerHTML = this.desc_name;

        // insert to card-inner
        [desc_icon, desc_name].forEach(
            (node, i, nodeList) => desc_item.appendChild(node)
        );

        return desc_item;
    }

    _bindEvents () {
        this.desc_item.addEventListener('click', () => {
            if(chosenArray.CHOSEN_RECORDS.indexOf(this.name_code) >= 0) {
                this.desc_item.classList.remove("active");
                chosenArray._recordOut(this.name_code);
                console.log(this.name_code + " released");
            } else {
                this.desc_item.classList.add("active");
                chosenArray._recordIn(this.dim_id, this.desc_name);
                console.log(this.name_code + " activated");
            }
        });

        // 实现数据绑定

    }
}


// 加载维度对应的描述词
function loadDescs (dim_id) {
    desc_list = new Array;
    $.ajax({
        url: `http://124.220.168.234/api/descriptors/?dim_id=${dim_id}`,
        async: false,
        type: "GET",
        contentType: "application/json",
        dataType: "json",
        success: function(res) {
            if(res["count"] > 0) {
                res["results"].forEach((desc_doc, _id, _) => {
                    desc_item = new DescItem(desc_doc['desc_id'], desc_doc['dim_id'], desc_doc['desc_name']);
                    desc_item._bindEvents('');
                    desc_list.push(desc_item);
                });
            }
        }
    });
    return desc_list;
}


class EmptyAll {
    constructor () {
        this.empty_btn = document.querySelector("#empty_records");
        this.target_pool = document.querySelector("#desc_pool");
        this.candid_pool = document.querySelector("#candid_pool");
        this.empty_btn.classList.remove("active");
    }

    _bindEvents () {
        this.empty_btn.addEventListener("click", () => {
            // 清空已选
            console.log(`Empty all ${chosenArray.CHOSEN_RECORDS.length} chosen descriptors.`);
            this.target_pool.childNodes.forEach((node, _id, _) => {
                node.classList.remove("active");
            });
            chosenArray._emptyAll();
            // 清空预测结果
            
        });
    }
}


// 加载用户已选中的描述词
class ChosenCard {
    constructor (dim_id, desc_name, desc_id=null, dim_name=null) {
        this.dim_id = dim_id;
        this.desc_id = desc_id;
        this.dim_name = dim_name;
        this.desc_name = desc_name;

        this.card_item = this._createItem();
        this.listener = document.querySelector("#chosen_descs");
        this._bindEvents();
    }

    _createItem () {
        let card_item = document.createElement("div");
        card_item.classList.add("card");

        let card_top = `<div class="card_top">${this.desc_name}</div>`;
        let card_bottom = `<div class="card_bottom">${this.dim_id+'.'+this.dim_name}</div>`;

        // insert to card-inner
        card_item.innerHTML = card_top + card_bottom;
        return card_item;
    }

    // 将记录对象同步至记录窗口
    _deploy () {
        this.listener.appendChild(this.card_item);
    }

    _bindEvents () {
        let name_code = `${this.dim_id}_${this.desc_name}`
        // 删除记录时，左侧选框还原
        this.card_item.addEventListener("click", () => {
            let desc_elem = document.querySelectorAll(`[n_code='${name_code}']`)[0];
            console.log(name_code + " released");
            if(desc_elem) {
                desc_elem.classList.remove("active");
            }
            chosenArray._recordOut(name_code);
        });
    }
}


// 历史记录框对象
class ChosenArray {
    constructor (candid_pool) {
        this.field = document.querySelector("#chosen_descs");
        // 记录已选内容的单位对象
        this.obj_list = new Array;
        this.CHOSEN_RECORDS = new Array;
        this.candid_pool = candid_pool;
    }

    _recordIn(dim_id, desc_name) {
        let name_code = dim_id + "_" + desc_name;
        let new_record = new ChosenCard(dim_id, desc_name);
        // 记录
        this.obj_list.push(new_record);
        this.__intoView(new_record.card_item);
        this.CHOSEN_RECORDS.push(name_code);
        this.candid_pool._freshPool(this.CHOSEN_RECORDS);
    }

    _recordOut(name_code=null) {
        let r_id = this.CHOSEN_RECORDS.indexOf(name_code);

        if(!name_code) {
            return -1;
        }
        
        if(r_id < 0) {
            return -1;
        }
        // 删除
        this.__outOfView(this.obj_list[r_id].card_item);
        this.obj_list.splice(r_id, 1);
        this.CHOSEN_RECORDS.splice(r_id, 1);
        this.candid_pool._freshPool(this.CHOSEN_RECORDS);
        return r_id;
    }

    _emptyAll() {
        this.CHOSEN_RECORDS.splice(0);
        this.obj_list.splice(0);
        this.field.innerHTML = '';
        this.candid_pool.pool.innerHTML = '';
    }

    __intoView(chosen_node) {
        this.field.appendChild(chosen_node);
    }

    __outOfView(chosen_node) {
        this.field.removeChild(chosen_node);
    }
}


class CandidPool {
    constructor () {
        this.pool = document.querySelector("#candid_pool");
        this.obj_list = new Array;
    }

    _freshPool(desc_list) {

        let that = this;

        if (desc_list.length <= 0) {
            return [];
        }

        $.ajax({
            type: 'POST',
            headers: {
                Accept: "*/*"
            },
            async: false,
            url: 'http://124.220.168.234/api/desc2targets?access_id=guest&charset=utf-8',
            data: JSON.stringify({
                "limitation": 45,
                "descriptors": desc_list,
                "user_name": "jkale"
            }),
            dataType: "json",
            contentType: "application/json; charset=utf-8",
            success: function(res) {
                that.obj_list = [];
                that.pool.innerHTML = '';
                that._loadCandids(res["targets"]);
            }
        });
    }

    _loadCandids(targets) {
        targets.forEach((c_name, _id, _) => {
            let candid_item = new CandidCard(c_name, 1,_id+1);
            this.obj_list.push(candid_item);
            this.pool.appendChild(candid_item.card_item);
        });
    }
}


class CandidCard {
    constructor (candid_name, confidence=-1, candid_id=-1) {
        this.candid_name = candid_name;
        this.confidence = confidence;
        this.candid_id = candid_id;

        this.card_item = this._createItem();
    }

    _createItem() {
        let card_item = document.createElement("div");
        card_item.classList.add("card");

        let card_top = `<div class="card_top">${this.candid_name}</div>`;
        let card_num = `<div class="card_num">No. ${this.candid_id}</div>`;
        let card_anno = `<div class="card_anno">${this.confidence}</div>`;
        let card_bottom = `<div class="card_bottom">${card_num + card_anno}</div>`;

        // insert to card-inner
        card_item.innerHTML = card_top + card_bottom;
        return card_item;
    }
}


// 存储选中的描述
// 存储选中的前n个目标词
class Hooker {
    constructor () {
        // 记录已选内容的单位对象
        this.CHOSEN_ITEMS = new Array;

        // 鱼饵集合：注册与修改信息的对象
        this.SHRIMP_POOL = new Array;
    }

    logIn(shrimp=new Shrimp, bait=null, setter=()=>{}, getter=()=>{} ) {
        bait = shrimp.getBait() || bait;
        setter = shrimp

        // 注册钩子：组件与数据挂钩
        // key: 挂钩属性
        // Obj: 虾米对象
        Object.defineProperty(shrimp, bait, {set: shrimp.setter, get: shrimp.getter});

        this.SHRIMP_POOL.push(shrimp);
        console.log("A new SHRIMP is successfully hooked!");
    }

    logOut() {
        // 注销钩子：组件与数据脱钩
    }

    _emptyAll() {
        this.CHOSEN_ITEMS.splice(0);
    }
}
